package com.hjxr.quota.define.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjxr.common.utils.bean.BeanUtils;
import com.hjxr.quota.define.constant.DefineConstant;
import com.hjxr.quota.define.domain.*;
import com.hjxr.quota.define.dto.DimensionVo;
import com.hjxr.quota.define.dto.QuotaAndValueVo;
import com.hjxr.quota.define.dto.QuotaCreateDto;
import com.hjxr.quota.define.mapper.*;
import com.hjxr.quota.define.service.QuotaService;
import com.hjxr.quota.theme.domain.QuotaThemeSet;
import com.hjxr.quota.theme.service.IQuotaThemeSetService;
import com.hjxr.quota.tool.query.BaseQueryTool;
import com.hjxr.quota.tool.query.QueryToolFactory;
import com.hjxr.quota.util.JdbcUtils;
import com.hjxr.quota.util.PageUtil;
import com.hjxr.quota.util.Query;
import com.hjxr.quota.datasource.domain.JobDatasource;
import com.hjxr.quota.datasource.domain.QuotaDimension;
import com.hjxr.quota.datasource.domain.QuotaDimensionDetail;
import com.hjxr.quota.datasource.domain.TablenameAlias;
import com.hjxr.quota.datasource.mapper.JobDatasourceMapper;
import com.hjxr.quota.datasource.mapper.QuotaDimensionMapper;
import com.hjxr.quota.datasource.mapper.TablenameAliasMapper;
import com.hjxr.quota.define.domain.*;
import com.hjxr.quota.define.mapper.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.*;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * @author ma
 * @date 2020/9/14 - 17:11
 **/
@Service
public class QuotaServiceImpl extends ServiceImpl<QuotaMapper, Quota> implements QuotaService {

    @Resource
    private QuotaSourceMapper quotaSourceMapper;
    @Resource
    private IQuotaThemeSetService quotaThemeSetService;
    @Resource
    private TablenameAliasMapper tablenameAliasMapper;
    @Resource
    private QuotaMapper quotaMapper;
    @Resource
    private QuotaDimensionMapper quotaDimensionMapper;
    @Resource
    private QuotaValueMapper quotaValueMapper;
    @Resource
    private DimRelationMapper dimRelationMapper;
    @Resource
    private QuotaDimRelationDetailMapper quotaDimRelationDetailMapper;
    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor executor;
    @Resource
    private QuotaFormulaMapper quotaFormulaMapper;
    @Resource
    private QuotaFormulaOperatorMapper quotaFormulaOperatorMapper;
    @Resource
    private JobDatasourceMapper jobDatasourceMapper;

    @Override
    public PageUtil getList(Map<String, Object> maps) {

        QueryWrapper<Quota> wrapper = new QueryWrapper<>();
        String keyword = (String) maps.get("keyword");
        String type = (String) maps.get("type");
        String themeId = (String) maps.get("themeId");
        String createType = (String) maps.get("createType");
        if (StringUtils.isNotBlank(keyword)) {
            wrapper.like("NAME" , keyword)
                    .or().like("UNAME" , keyword)
                    .or().like("CODE" , keyword)
                    .or().like("LABLE" , keyword);
        }
        if (StringUtils.isNotBlank(type)) {
            wrapper.eq("TYPE" , type);
        }
        if (StringUtils.isNotBlank(themeId)) {
            wrapper.eq("THEME_SET_ID" , Integer.valueOf(themeId));
        }
        if (StringUtils.isNotBlank(createType)) {
            wrapper.eq("CREATE_TYPE" , createType);
        }
        IPage<Quota> page = this.page(
                new Query<Quota>().getPage(maps),
                wrapper
        );
        List<Quota> records = page.getRecords();
        if (null != records && records.size() > 0) {
            //设置主题名
            Future<Map<Integer, QuotaThemeSet>> setNames = executor.submit(() -> {
                List<Integer> setIds = records.stream().map(Quota::getThemeSetId).collect(Collectors.toList());
                Map<Integer, QuotaThemeSet> collect = quotaThemeSetService.getThemeSetByIdIn(setIds)
                        .stream()
                        .collect(Collectors.toMap(QuotaThemeSet::getId, a -> a, (k1, k2) -> k1));
                return collect;
            });
            Future<Map<Integer, QuotaValue>> values = executor.submit(() -> {
                List<Integer> quotaIdS = records.stream().map(Quota::getId).collect(Collectors.toList());
                List<QuotaValue> quotaValues = quotaValueMapper.selectList(new QueryWrapper<QuotaValue>().in("QUOTA_ID" , quotaIdS));
                for (QuotaValue q : quotaValues) {
                    String dimensions = q.getDimensions();
                    if (StringUtils.isNotBlank(dimensions)) {
                        dimensions.replaceAll("，" , ",");
                        List<QuotaDimension> dim = quotaDimensionMapper.selectList(new QueryWrapper<QuotaDimension>().in("ID" , dimensions.split(",")));
                        String dimension = dim.stream().map(item -> item.getDimensionName()).collect(Collectors.joining("|"));
                        q.setDimensionNames(dimension);
                    }
                }
                Map<Integer, QuotaValue> valueMap = quotaValues.stream().collect(Collectors.toMap(QuotaValue::getQuotaId, a -> a, (k1, k2) -> k1));
                return valueMap;
            });

            try {
                w:
                while (true) {
                    if (setNames.isDone() && !setNames.isCancelled() && values.isDone() && !values.isCancelled()) {
                        f:
                        for (Quota record : records) {
                            Map<Integer, QuotaThemeSet> collect = setNames.get();
                            QuotaThemeSet quotaThemeSet = collect.get(record.getThemeSetId());
                            if (quotaThemeSet != null) {
                                record.setThemeSetTitle(quotaThemeSet.getSetTitle());
                            }
                            Map<Integer, QuotaValue> valueMap = values.get();
                            QuotaValue quotaValue = valueMap.get(record.getId());
                            if (quotaValue != null) {
                                record.setMeasure(quotaValue.getMeasure());
                                record.setValue(quotaValue.getValue());
                                record.setDimensionNames(quotaValue.getDimensionNames());
                                record.setSm(quotaValue.getSm());
                                record.setAv(quotaValue.getAv());
                                record.setCt(quotaValue.getCt());
                                record.setMx(quotaValue.getMx());
                                record.setMn(quotaValue.getMn());
                            }
                        }
                        break w;
                    } else {
                        Thread.sleep(1);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

        }
        return new PageUtil(page);
    }

    @Override
    public PageUtil queryList(Map<String, Object> maps) {
        QueryWrapper<Quota> wrapper = new QueryWrapper<>();
        String themeSetId = (String) maps.get("themeSetId");
        if (StringUtils.isNotBlank(themeSetId)) {
            wrapper.eq("THEME_SET_ID" , Integer.valueOf(themeSetId));
        }
        IPage<Quota> page = this.page(
                new Query<Quota>().getPage(maps),
                wrapper
        );
        return new PageUtil(page);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public Boolean createQuota(List<QuotaCreateDto> quotaCreateDtos) {
        try {
            Quota quota = new Quota();
            QuotaSource quotaSource = new QuotaSource();
            for (QuotaCreateDto quotaCreateDto : quotaCreateDtos) {
                BeanUtils.copyProperties(quotaCreateDto, quota);
                save(quota);//插入指标表
                //插入指标来源表
                BeanUtils.copyProperties(quotaCreateDto, quotaSource);
                quotaSource.setQuotaId(quota.getId());
                quotaSourceMapper.insert(quotaSource);
            }
            return true;

        } catch (BeansException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public R saveCustomQuota(QuotaCreateDto quotaCreateDto) {
        try {
            Map<String, String> dimMap = quotaCreateDto.getDimMap();
            Set<String> nodeIds = dimMap.keySet();
            Set<String> rootNodeIds = new HashSet<>(dimMap.values());
            Date date = new Date();
            //指标数据
            Quota quota = new Quota();
            quota.setStatus("1");
            BeanUtils.copyProperties(quotaCreateDto, quota);
            quota.setUpdateDate(date);
            quotaMapper.insert(quota);
            //插入指标来源表
            QuotaSource quotaSource = new QuotaSource();
            BeanUtils.copyProperties(quotaCreateDto, quotaSource);
            quotaSource.setUpdateDate(date);
            quotaSource.setQuotaId(quota.getId());
            quotaSource.setSCol(quotaCreateDto.getMeasureCol());
            quotaSourceMapper.insert(quotaSource);
            //这里存储的指标与一级维度的关系 map里取出来需要去重
            for (String rootNodeId : rootNodeIds) {
                DimRelation dimRelation = new DimRelation();
                dimRelation.setQuotaId(quota.getId());
                dimRelation.setDimensionId(Integer.valueOf(rootNodeId));
                dimRelation.setUpdateDate(date);
                dimRelationMapper.insert(dimRelation);
            }
            StringBuilder sb = new StringBuilder().append(",");
            //这里存储的是指标与维度非根节点的数据
            for (String nodeId : nodeIds) {
                sb.append(nodeId).append(",");
                QuotaDimRelationDetail quotaDimRelationDetail = new QuotaDimRelationDetail();
                quotaDimRelationDetail.setRootDimId(Integer.valueOf(dimMap.get(nodeId)));
                quotaDimRelationDetail.setQuotaId(quota.getId());
                quotaDimRelationDetail.setDimensionId(Integer.valueOf(nodeId));
                quotaDimRelationDetail.setUpdateDate(date);
                quotaDimRelationDetailMapper.insert(quotaDimRelationDetail);
            }
            QuotaValue quotaValue = new QuotaValue();
            quotaValue.setQuotaId(quota.getId());
            //指标值数据
            quotaValue.setDimensions(sb.toString());
            quotaValue.setMeasure(quotaCreateDto.getMeasureValue());
            quotaValue.setCode(quota.getCode());
            quotaValue.setUpdateDate(date);
            //如果是sql创建需要重新执行sql处理
            if (DefineConstant.QuotaCreateTypeEnum.IS_SQL.getCode().equals(quota.getCreateType()) && StringUtils.isNotBlank(quotaCreateDto.getMeasureCol())) {
                //获取连接
                JobDatasource datasource = jobDatasourceMapper.selectById(quotaSource.getDatasourceId());
                BaseQueryTool queryTool = QueryToolFactory.getByDbType(datasource);
                Connection connection = queryTool.getConnection();
                // 执行sql查询
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery(quotaSource.getQsql());
                ResultSetMetaData metaData = rs.getMetaData();
                List<BigDecimal> list = new ArrayList<>();
                while (rs.next()) {
                    int columnCount = metaData.getColumnCount();
                    for (int i = 1; i <= columnCount; i++) {
                        //获得指定列的列名
                        String columnName = metaData.getColumnName(i);
                        if (columnName.equals(quotaCreateDto.getMeasureCol())) {
                            String columnValue = rs.getString(i);
                            list.add(new BigDecimal(columnValue));
                        }
                    }
                }
                BigDecimal max = list.stream().max((x1, x2) -> x1.compareTo(x2)).get();
                BigDecimal min = list.stream().min((x1, x2) -> x1.compareTo(x2)).get();
                BigDecimal sum = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal avg = sum.divide(BigDecimal.valueOf(list.size()), 2, BigDecimal.ROUND_HALF_UP);
                quotaValue.setValue(sum.floatValue());
                quotaValue.setSm(sum.floatValue());
                quotaValue.setAv(avg.floatValue());
                quotaValue.setMx(max.floatValue());
                quotaValue.setMn(min.floatValue());
                quotaValue.setCt(list.size());
            } else {
                quotaValue.setValue(quotaCreateDto.getQuotaValue());
                quotaValue.setSm(quotaCreateDto.getQuotaValue());
            }
            quotaValueMapper.insert(quotaValue);
            return R.ok(true);
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.failed("执行异常");
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean createDimension(List<DimensionVo> dimensionVos, String username) {
        try {
            TablenameAlias tablenameAlias = tablenameAliasMapper.selectById(dimensionVos.get(0).getTablenameAliasId());
            for (DimensionVo dimensionVo : dimensionVos) {
                List<String> columnValue = quotaMapper.selectColumnValue(tablenameAlias.getTableName(), dimensionVo.getColumnName());
                QuotaDimension dimension = new QuotaDimension();
                BeanUtils.copyProperties(dimensionVo, dimension);
                dimension.setDimensionAttr("2");
                dimension.setStatus("1");
                dimension.setDimensionType("2");
                dimension.setUpperId(0);
                quotaDimensionMapper.insert(dimension);
                List<QuotaDimensionDetail> list = new ArrayList<>();
                for (String value : columnValue) {
                    QuotaDimensionDetail dimensionDetail = new QuotaDimensionDetail();
                    dimensionDetail.setDimensionId(dimension.getId());
                    dimensionDetail.setCodeValue(value);
                    dimensionDetail.setColnameId(dimensionVo.getId());
                    list.add(dimensionDetail);
                }
                quotaMapper.insertDimensionDetails(list);
            }
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Map<String, Object> getQuotaAndValue(Map<String, Object> params) {
        Map<String, Object> resultMap = new HashMap<>();
        Integer flag = (Integer) params.get("flag");
        Integer pageNum = (Integer) params.get("pageNum");
        Integer pageSize = (Integer) params.get("pageSize");
        List<Integer> quotaIds = (List<Integer>) params.get("quotaIds");
        List<Integer> themeIds = (List<Integer>) params.get("themeIds");
        List<QuotaAndValueVo> list = quotaValueMapper.selectQuotaAndValue(themeIds, quotaIds, pageNum * pageSize, (pageNum - 1) * pageSize + 1);
        Integer count = quotaValueMapper.selectQuotaAndValueCount(themeIds, quotaIds, pageNum * pageSize, (pageNum - 1) * pageSize + 1);

        if (list != null && list.size() > 0) {
            list.forEach(quotaValue -> {
                String dimensions = quotaValue.getDimensions();
                List<QuotaDimension> dim = quotaDimensionMapper.selectList(new QueryWrapper<QuotaDimension>().in("ID" , dimensions.replaceAll("，" , ",").split(",")));
                String dimension = dim.stream().map(item -> item.getDimensionName()).collect(Collectors.joining("|"));
                quotaValue.setDimensionName(dimension);
            });
        }
        resultMap.put("data" , list);
        resultMap.put("count" , count);
        return resultMap;
    }

    @Override
    @Transactional
    public Boolean saveQuota(QuotaCreateDto quotaCreateDto) {
        quotaCreateDto.setCreateDate(new Date());
        try {

            Quota quota = new Quota();
            QuotaSource quotaSource = new QuotaSource();
            BeanUtils.copyProperties(quotaCreateDto, quota);
            BeanUtils.copyProperties(quotaCreateDto, quotaSource);
            if (quotaSourceMapper.selectList(new QueryWrapper<QuotaSource>().eq("COLNAME_ID" , quotaSource.getColnameId())).size() == 0) {
                quotaMapper.insert(quota);
                //插入指标来源表

                quotaSource.setQuotaId(quota.getId());
                quotaSourceMapper.insert(quotaSource);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public Map<String, String> getQuotaDetail(Integer id) {
        Map<String, String> map = new HashMap<>();
        //当前预指标
        Quota quota = quotaMapper.selectById(id);
        if (quota != null) {
            // 如果指标为使用指标生成  查询指标公式组装公式数据  顺便使用ENUM去除魔法值
            if (DefineConstant.QuotaCreateTypeEnum.IS_QUOTA.getCode().equals(quota.getCreateType())) {
                List<QuotaFormula> quotaFormulas = quotaFormulaMapper.selectList(new QueryWrapper<QuotaFormula>().eq("QUOTA_ID" , quota.getId()).orderByAsc("ORDER_NUM"));
                //组装计算公式
                StringBuilder sb = new StringBuilder();
                quotaFormulas.forEach(item -> {
                    if (DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(item.getFormulaType())) {
                        Quota computeQuota = quotaMapper.selectById(item.getFormulaTextId());
                        sb.append("『").append(computeQuota.getName()).append("➢值:").append(item.getFormulaValue()).append("』");
                    } else {
                        QuotaFormulaOperator operator = quotaFormulaOperatorMapper.selectById(item.getFormulaTextId());
                        sb.append(operator.getOperator());
                    }
                });
                map.put("formula" , sb.toString());
            }
            if (DefineConstant.QuotaCreateTypeEnum.IS_SQL.getCode().equals(quota.getCreateType())) {
                List<QuotaSource> quotaSources = quotaSourceMapper.selectList(new QueryWrapper<QuotaSource>().eq("QUOTA_ID" , quota.getId()));
                if (null != quotaSources && quotaSources.size() > 0) {
                    QuotaSource quotaSource = quotaSources.get(0);
                    map.put("sql" , quotaSource.getQsql());
                    JobDatasource datasource = jobDatasourceMapper.selectById(quotaSource.getDatasourceId());
                    map.put("datasource" , datasource.getDatasource());
                    map.put("datasourceName" , datasource.getDatasourceName());
                }
            }
            map.put("quotaId" , id + "");
            map.put("type" , getType(quota.getType()));
            map.put("createType" , getCreateType(quota.getCreateType()));
            map.put("createBy" , quota.getCreateBy());
            map.put("createDate" , DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(quota.getCreateDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
        } else {
            map.put("type" , "暂无数据");
            map.put("createType" , "暂无数据");
            map.put("createBy" , "暂无数据");
            map.put("createDate" , "暂无数据");
        }
        return map;
    }

    @Override//查询当前指标溯源
    public List<QuotaFormula> lookForSource(Integer id) {
        //查询公式数据
        List<QuotaFormula> formulas = quotaFormulaMapper.selectList(new QueryWrapper<QuotaFormula>().eq("QUOTA_ID" , id).orderByAsc("ORDER_NUM"));
        List<QuotaFormula> quotaFormulas = formulas.stream().filter(quotaFormula -> DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(quotaFormula.getFormulaType()))
                .collect(Collectors.toList());
        //递归往上查
        getRootIds(quotaFormulas);
        return quotaFormulas;
    }

    @Override
    public R executeSql(Map<String, String> params) {
        Integer datasourceId = Integer.valueOf(params.get("datasourceId"));
        String sql = params.get("sql");
        Integer isPage = Integer.valueOf(params.get("isPage"));
        String countSql = "";
        Statement stmt = null;
        ResultSet rs = null;

        //返回数据结构
        Map<String, Object> resultMap = new HashMap<>();
        List<Map<String, String>> resultList = new ArrayList<>();
        Map<String, String> columnMap = new HashMap<>();
        try {
            //获取连接
            JobDatasource datasource = jobDatasourceMapper.selectById(datasourceId);
            //如果选择分页 sql语句自动增加分页
            if (1 == isPage && "oracle".equals(datasource.getDatasource())) {
                Integer pageNum = Integer.valueOf(params.get("pageNum"));
                Integer pageSize = Integer.valueOf(params.get("pageSize"));
                String oraclePage = DefineConstant.ORACLE_PAGE;
                countSql = String.format(DefineConstant.ORACLE_PAGE_COUNT, sql);
                sql = String.format(oraclePage, sql, pageNum * pageSize, (pageNum - 1) * pageSize+1);
            }
            BaseQueryTool queryTool = QueryToolFactory.getByDbType(datasource);
            Connection connection = queryTool.getConnection();
            // 执行sql查询
            stmt = connection.createStatement();
            rs = stmt.executeQuery(sql);
            ResultSetMetaData metaData = rs.getMetaData();
            while (rs.next()) {
                int columnCount = metaData.getColumnCount();
                Map<String, String> map = new HashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    //获得指定列的列名
                    String columnName = metaData.getColumnName(i);
                    String columnType = metaData.getColumnTypeName(i);
                    columnMap.put(columnName, columnType);
                    //获得指定列的列值
                    String columnValue = rs.getString(i);
                    map.put(columnName, columnValue);
                }
                resultList.add(map);
            }
            if (1 == isPage && "oracle".equals(datasource.getDatasource())) {
                Integer count = getCount(datasource, countSql);
                resultMap.put("count" , count);
            }
            resultMap.put("data" , resultList);
            resultMap.put("label" , columnMap);
        } catch (SQLException e) {
            return R.failed("SQL执行异常");
        } finally {
            JdbcUtils.close(rs);
            JdbcUtils.close(stmt);
        }
        return R.ok(resultMap);
    }

    public Integer getCount(JobDatasource datasource, String sql) {
        Statement stmt = null;
        ResultSet rs = null;
        Integer count = 0;
        try {
            BaseQueryTool queryTool = QueryToolFactory.getByDbType(datasource);
            Connection connection = queryTool.getConnection();
            // 执行sql查询
            stmt = connection.createStatement();
            rs = stmt.executeQuery(sql);
            if (rs.next()) {//光标向后移动，并判断是否有效
                count = rs.getInt(1);//对总记录数赋值
            }
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        } finally {
            JdbcUtils.close(stmt);
            JdbcUtils.close(rs);
        }
        return count;
    }

    //递归查询
    private void getRootIds(List<QuotaFormula> list) {
        for (QuotaFormula qf : list) {
            //拼接当前预指标名称和指标值
            Quota quota = quotaMapper.selectById(qf.getFormulaTextId());
            StringBuilder sb = new StringBuilder();
            sb.append("『").append(quota.getName()).append("➢值:").append(qf.getFormulaValue()).append("』");
            qf.setQuotaName(sb.toString());
            //再次获取上层公式数据
            List<QuotaFormula> formulas = quotaFormulaMapper.selectList(new QueryWrapper<QuotaFormula>().eq("QUOTA_ID" , qf.getFormulaTextId()).orderByAsc("ORDER_NUM"));
            List<QuotaFormula> quotaFormulas = formulas.stream().filter(quotaFormula -> DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(quotaFormula.getFormulaType()))
                    .collect(Collectors.toList());
            if (quotaFormulas != null && quotaFormulas.size() > 0) {
                StringBuilder builder = new StringBuilder();
                for (QuotaFormula formula : formulas) {
                    //拼接预指标名称
                    if (DefineConstant.FormulaTypeEnum.IS_QUOTA.getCode().equals(formula.getFormulaType())) {
                        Quota quotaData = quotaMapper.selectById(formula.getFormulaTextId());
                        builder.append(quotaData.getName());
                    } else {//拼接运算符数据
                        QuotaFormulaOperator quotaFormulaOperator = quotaFormulaOperatorMapper.selectById(formula.getFormulaTextId());
                        builder.append(quotaFormulaOperator.getOperator());
                    }
                }
                //设置公式
                qf.setFormula(builder.toString());
                //设置上层节点
                qf.setRootIds(quotaFormulas);
                //递归
                getRootIds(quotaFormulas);
            }
        }
    }

    private String getType(String type) {
        switch (type) {
            case "1":
                return "元数据指标";
            case "2":
                return "业务指标";
            case "3":
                return "政策型指标";
            case "4":
                return "预测指标";
            default:
                return "其他";
        }
    }

    private String getCreateType(String createType) {
        if (StringUtils.isBlank(createType)) {
            return "未知类型";
        }
        switch (createType) {
            case "1":
                return "数据库表创建";
            case "2":
                return "自定义创建";
            case "3":
                return "根据指标创建";
            case "4":
                return "根据语句创建";
            default:
                return "其他";
        }
    }
}
